ref 是 React 中用來取得 DOM 節點的一個方法,通常是使用 ref 來處理以下這些行為:
focus、選擇文字等ref,因為用這種方式取得 DOM 元素固然方便,但使用過多可能會導致產品程式碼長期維護上的不便。另外還有一點要注意的是,在 function component 中是無法使用 ref 的,因為 function component 沒有 instance。ref 有兩種方式,分別是使用 React.createRef() 和 回調式 ref。React.createRef() 是 React 中的一個方法,可以創建 ref。下面我們透過調用 React.createRef() 創建 ref 並賦給 myRef 變數,再將 myRef 放到標籤本身的 ref 屬性上,這樣就能透過 myRef 取得該標籤。
我們創建的 ref 本身是一個物件,裡面有一個屬性 { current: node },這個 current 就是我們要取得的 DOM 節點,在下面的範例中,就是 div。這個 current 當然也包含了一些 HTML 的屬性,比方範例中透過 innerHTML 取得 HTML 內的內容。
class MyComponent extends React.Component {
// 創建 ref
myRef = React.createRef();
componentDidMount () {
console.log(this.myRef); //訪問 ref 物件
console.log(this.myRef.current); //訪問 DOM 節點
console.log(this.myRef.current.innerHTML); // 訪問 DOM 的 HTML 內容
}
render () {
return <div ref={ this.myRef }>內容</div>
}
}
我們也可以透過回調函數來使用 ref。下面的範例中,我們透過在 div 上增加 ref 屬性,並利用 ref 的回調函數取得節點,這個回調函數的參數本身就是 DOM 節點。
class MyComponent extends React.Component {
// 創建 ref
myRef = null;
componentDidMount () {
console.log(this.myRef); //直接取得 DOM 節點
console.log(this.myRef.innerHTML); // 訪問 DOM 的 HTML 內容
}
render () {
// 透過 ref 回調函數來取得 DOM 節點
return <div ref={node => this.myRef = node }>內容</div>
}
}
ref 有不少運用方式和時機,其中一個就是像前面提到的,利用 ref 做 focus 的行為。下面的範例中,我們先創建一個 ref 並賦給 textInput,並放入到 input 標籤的 ref 中,這樣就能取得它的 DOM,同時我們透過 focusInput 函式去調用 textInput 執行綁定動作,這樣當點擊按鈕時,就會 focus 在 input 上
class UserProfile extends React.Component {
constructor() {
super ();
this.textInput = React.createRef();
this.focusInput = this.focusInput.bind(this);
}
focusInput() {
this.textInput.current.focus();
}
render() {
return (
<div>
<input
type="text"
ref={this.textInput} />
<button onClick={this.focusInput}>click</button>
</div>
);
}
}
我們也可以直接在 component 上面使用 ref,來取得 component 內的 DOM,讓元件在 mounting 完之後就自動 focus,不過這種作法一樣是只能用在 class component 上。React 是在 mounting 的階段去處理 ref,將 DOM element 賦到 ref 的 current 屬性中,在 unmounting 時再去清空回 null 狀態。至於 ref 的更新是發生在 componentDidMount 或 componentDidUpdate 之前。
// 在元件中使用 ref 取得 DOM element
class TextInput extends React.Component {
constructor() {
super();
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
this.textInput.current.focus();
}
render () {
return <div>
<input
type="text"
ref={this.textInput}
/>
<button onClick={this.focusInput}>click</button>
</div>
}
}
class UserProfile extends React.Component {
constructor() {
super();
this.textInput = React.createRef();
}
componentDidMount() {
this.textInput.current.focusTextInput();
}
render() {
// 在 component 上使用 ref,直接去取得 component 內的 DOM 並執行 focus 行為
return (
<div>
<TextInput ref={this.textInput} />
</div>
);
}
}
這一篇主要是整理 ref 的基本用法,除了課程內容外,也有參考官網的說明和範例,因為官網講得更為詳細(也讓我看的頭很痛)。下一篇會透過表單事件處理,來更了解 react 中 event 和 ref 的使用。